package
{
	import flare.display.TextSprite;
	import flare.physics.Spring;
	
	import flash.display.*;
	import flash.events.*;
	import flash.geom.Matrix;
	import flash.net.*;
	import flash.utils.*;
	import flash.xml.XMLNode;
	
	public class CareerSpace extends Sprite
	{
		private var backEnd:BackEnd;
		
		private var axis:Axis;
		
		private var pathArray:Array;
		private var indexPathSelected:int;
		
		private var urlLoader:URLLoader;
		private var originalXML:XML;
		
		private var debugText:TextSprite;
		
		private var startingPoint:String;
		private var endingPoint:String;

		
		public function CareerSpace()
		{
			// draw background
			var bg:Sprite = new Sprite();
			var mat:Matrix = new Matrix();
			mat.createGradientBox(800, 600, Math.PI / 2, 0, 100);
			bg.graphics.beginGradientFill(GradientType.LINEAR,
				new Array(0x000000, 0xAAAAAA),
				new Array(1, 1),
				new Array(0x00, 0xFF),
				mat);
			bg.graphics.drawRect(0, 0, 800, 600);
			bg.graphics.endFill();
			this.addChild(bg);
			
			// load data
			urlLoader = new URLLoader();
			urlLoader.load(new URLRequest("../data/profiles.xml"));
			urlLoader.addEventListener(Event.COMPLETE, onLoad);
			this.addEventListener("BackEndReady", init);
			
			// initialize input data
			this.startingPoint = "";
			this.endingPoint = "";
			
			// debug text
			debugText = new TextSprite();
			debugText.visible = true;
			this.addChild(debugText);
		}
		
		private function onLoad(e:Event):void {
			// construct backend and convert into profile data
			
			originalXML = new XML(urlLoader.data);
			backEnd = new BackEnd(originalXML.children());
			
			this.dispatchEvent(new Event("BackEndReady", true));
		}
		
		private function init(e:Event):void {
			var profiles:XMLList = backEnd.getChildren();
			
			// build axis according to backEnd
			axis = new Axis(backEnd);
			this.addChild(axis);
			
			// build career paths according to profiles
			pathArray = new Array();
			for (var i:int = 0; i < profiles.length(); i++) {
				pathArray.push(new CareerPath(profiles[i], axis));
			}
			this.draw();
			this.indexPathSelected = -1;  // nothing selected initially
			
			// add event listeners from children
			this.addEventListener("PATH_SELECTED", onPathSelected);
			//this.addEventListener("JOB_SELECTED", onJobSelected);
			//this.addEventListener("STEP_SELECTED", onStepSelected);
		}
		
		//////////////////////////////////////////////////////////////////////
		// text input field interaction function
		//////////////////////////////////////////////////////////////////////
		public function setStartingPoint(txt:String):void {
			if (txt.length == 0)
				return;
			
			this.startingPoint = txt;
			
			txt = txt.toLowerCase();
			var inputSegs:Array = txt.split(",");
			
			for (var i:int = 0; i < pathArray.length; i++) {
				var job:Job = pathArray[i].arrayJob[0];
				var firstJobPosition:String = job.getPosition().toLowerCase();
				var firstJobField:String = job.getField().toLowerCase();
				
				pathArray[i].visible = false;  // first hide all
				
				if ((firstJobPosition == trim(inputSegs[0].toString()) && firstJobField == trim(inputSegs[1].toString())) ||
					(firstJobPosition == trim(inputSegs[1].toString()) && firstJobField == trim(inputSegs[0].toString()))) {
					pathArray[i].visible = true;  // display only when match
				}
			}
			
			draw();
		}
		
		public function setEndignPoint(txt:String):void {
			if (txt.length == 0)
				return;
			
			this.endingPoint = txt;
			
			txt = txt.toLowerCase();
			var inputSegs:Array = txt.split(",");
			
			for (var i:int = 0; i < pathArray.length; i++) {
				var job:Job = pathArray[i].arrayJob[pathArray[i].arrayJob.length - 1];
				var desiredJobPosition:String = job.getPosition().toLowerCase();
				var desiredJobField:String = job.getField().toLowerCase();
				
				if (pathArray[i].visible == true) {  // work only on those visible paths
					pathArray[i].visible = false;  // first hide all
					
					if ((desiredJobPosition == inputSegs[0].toString()) ||
						(desiredJobPosition == inputSegs[1].toString()) ||
						(desiredJobField == inputSegs[0].toString()) ||
						(desiredJobField == inputSegs[1].toString())) {
						pathArray[i].visible = true;  // display only when match
					}
				}
			}
			
			draw();
		}
		
		
		//////////////////////////////////////////////////////////////////////
		// mouse interaction function
		//////////////////////////////////////////////////////////////////////
		private function onPathSelected(e:Event):void {
			// notify parent, the career gps demo
			// to disply this particular path information on the right
			for (var i:int = 0; i < this.pathArray.length; i++) {
				if (pathArray[i] == e.target) {
					this.indexPathSelected = i;  // set index pointing to selected path
					
					//dispInfo(i.toString(), 0, 500);
				}
			}
			
			this.dispatchEvent(new Event("SELECTED_PATH_FOUND", true));
		}
		
		public function getSelectedPath():CareerPath {
			return this.pathArray[this.indexPathSelected];
		}
		
		public function getPathStats():Array {
			var result:Array = new Array();
			
			// collect all career paths that are currently visible
			for (var i:int = 0; i < this.pathArray.length; i++) {
				if (pathArray[i].visible == true) {
					result.push(new Array(
						pathArray[i].arrayJob[0].getField() + ", " +
						pathArray[i].arrayJob[0].getPosition() + " -\n" +
						pathArray[i].arrayJob[pathArray[i].arrayJob.length-1].getField() + ", " +
						pathArray[i].arrayJob[pathArray[i].arrayJob.length-1].getPosition(),
						"1"));
				}
			}
			
			// merge results
			/*
			var mergedResult:Array = new Array();
			for (var i:int = 0; i < result.length; i++) {
				// unique key? add new entry
				
				// not unique key? increment
			}
			*/

			return result;
		}
		
		/*
		private function onJobSelected(e:Event):void {
			var jobSelected:Job;
			for (var i:int = 0; i < pathArray.length; i++) {
				for (var j:int = 0; j < pathArray[i].arrayJob.length; j++) {
					if (pathArray[i].arrayJob[j].isSelected()) {
						jobSelected = pathArray[i].arrayJob[j]; 
					}
				}
			}
			
			for (var i:int = 0; i < pathArray.length; i++) {
				pathArray[i].visible = false;
				for (var j:int = 0; j < pathArray[i].arrayJob.length; j++) {
					if (pathArray[i].arrayJob[j].equals(jobSelected)) {
						pathArray[i].visible = true;
					}
				}
			}
			
			draw();
		}
		
		private function onStepSelected(e:Event):void {
			// do nothing
			//dispInfo("SSSSSS", 0, 500);
		}
		*/
		
		//////////////////////////////////////////////////////////////////////
		// draw the paths
		//////////////////////////////////////////////////////////////////////
		private function draw():void {
			for (var i:int = 0; i < pathArray.length; i++) {
				this.addChild(pathArray[i]);
			}
		}
		
		
		//////////////////////////////////////////////////////////////////////
		// utility functions
		//////////////////////////////////////////////////////////////////////
		private function trim(str:String) : String {
			return str.replace(/^\s+|\s+$/g, '');
		}
		
		public function dispInfo(str:String, x:int, y:int):void {
			debugText.text = str;
			debugText.color = 0xFF0000;
			debugText.size = 30;
			debugText.x = x;
			debugText.y = y;
		}
	}
}